use crate::resp::decode::extract_fixed_data;
use crate::resp::error::RespError;
use crate::resp::{RespDecode, RespEncode, RespFrame, CRLF_LEN};
use bytes::{Buf, BytesMut};
use std::ops::{Deref, DerefMut};

#[derive(Debug, PartialEq, Eq, Clone)]
pub struct BuckString(pub(crate) Vec<u8>);

#[derive(Debug, PartialEq, Eq, Clone)]
pub struct RespNullBulkString;

impl Deref for BuckString {
    type Target = Vec<u8>;
    fn deref(&self) -> &Self::Target {
        &self.0
    }
}

impl DerefMut for BuckString {
    fn deref_mut(&mut self) -> &mut Self::Target {
        &mut self.0
    }
}

impl BuckString {
    pub fn new(s: impl Into<Vec<u8>>) -> Self {
        BuckString(s.into())
    }
}

impl<const N: usize> From<&[u8; N]> for BuckString {
    fn from(value: &[u8; N]) -> Self {
        BuckString(value.to_vec())
    }
}

impl From<&[u8]> for BuckString {
    fn from(s: &[u8]) -> Self {
        BuckString(s.to_vec())
    }
}

impl<const N: usize> From<[u8; N]> for RespFrame {
    fn from(value: [u8; N]) -> Self {
        BuckString(value.to_vec()).into()
    }
}

impl AsRef<[u8]> for BuckString {
    fn as_ref(&self) -> &[u8] {
        &self.0
    }
}

impl From<&str> for BuckString {
    fn from(s: &str) -> Self {
        BuckString(s.as_bytes().to_vec())
    }
}

impl From<String> for BuckString {
    fn from(s: String) -> Self {
        BuckString(s.into_bytes())
    }
}

impl RespEncode for RespNullBulkString {
    fn encode(self) -> Vec<u8> {
        b"$-1\r\n".to_vec()
    }
}

impl RespEncode for BuckString {
    fn encode(self) -> Vec<u8> {
        let mut buf = Vec::with_capacity(self.len() + 16);
        buf.extend_from_slice(&format!("${}\r\n", self.len()).into_bytes());
        buf.extend_from_slice(&self);
        buf.extend_from_slice(b"\r\n");
        buf
    }
}

impl RespDecode for RespNullBulkString {
    const PREFIX: &'static str = "$";
    fn decode(buf: &mut BytesMut) -> Result<Self, RespError> {
        extract_fixed_data(buf, "$-1\r\n", "NullBulkString")?;
        Ok(RespNullBulkString)
    }
    fn expect_length(_buf: &[u8]) -> Result<usize, RespError> {
        Ok(5)
    }
}

impl RespDecode for BuckString {
    const PREFIX: &'static str = "$";
    fn decode(buf: &mut BytesMut) -> Result<Self, RespError> {
        let (end, len) = crate::resp::decode::parse_length(buf, Self::PREFIX)?;
        let remained = &buf[end + CRLF_LEN..];
        if remained.len() < len + CRLF_LEN {
            return Err(RespError::NotComplete);
        }

        buf.advance(end + CRLF_LEN);

        let data = buf.split_to(len + CRLF_LEN);
        Ok(BuckString::new(data[..len].to_vec()))
    }

    fn expect_length(buf: &[u8]) -> Result<usize, RespError> {
        let (end, len) = crate::resp::decode::parse_length(buf, Self::PREFIX)?;
        Ok(end + CRLF_LEN + len + CRLF_LEN)
    }
}
